// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "skia/ext/skia_trace_memory_dump_impl.h"

#include "base/trace_event/memory_allocator_dump.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/process_memory_dump.h"
#include "skia/ext/SkDiscardableMemory_chrome.h"

namespace skia {

namespace {
    const char kMallocBackingType[] = "malloc";
}

SkiaTraceMemoryDumpImpl::SkiaTraceMemoryDumpImpl(
    base::trace_event::MemoryDumpLevelOfDetail level_of_detail,
    base::trace_event::ProcessMemoryDump* process_memory_dump)
    : SkiaTraceMemoryDumpImpl("", level_of_detail, process_memory_dump)
{
}

SkiaTraceMemoryDumpImpl::SkiaTraceMemoryDumpImpl(
    const std::string& dump_name_prefix,
    base::trace_event::MemoryDumpLevelOfDetail level_of_detail,
    base::trace_event::ProcessMemoryDump* process_memory_dump)
    : dump_name_prefix_(dump_name_prefix)
    , process_memory_dump_(process_memory_dump)
    , request_level_(
          level_of_detail == base::trace_event::MemoryDumpLevelOfDetail::LIGHT
              ? SkTraceMemoryDump::kLight_LevelOfDetail
              : SkTraceMemoryDump::kObjectsBreakdowns_LevelOfDetail)
{
}

SkiaTraceMemoryDumpImpl::~SkiaTraceMemoryDumpImpl() { }

void SkiaTraceMemoryDumpImpl::dumpNumericValue(const char* dumpName,
    const char* valueName,
    const char* units,
    uint64_t value)
{
    auto dump = process_memory_dump_->GetOrCreateAllocatorDump(dumpName);
    dump->AddScalar(valueName, units, value);
}

void SkiaTraceMemoryDumpImpl::setMemoryBacking(const char* dumpName,
    const char* backingType,
    const char* backingObjectId)
{
    if (strcmp(backingType, kMallocBackingType) == 0) {
        auto dump = process_memory_dump_->GetOrCreateAllocatorDump(dumpName);
        const char* system_allocator_name = base::trace_event::MemoryDumpManager::GetInstance()
                                                ->system_allocator_pool_name();
        if (system_allocator_name) {
            process_memory_dump_->AddSuballocation(dump->guid(),
                system_allocator_name);
        }
    } else {
        NOTREACHED();
    }
}

void SkiaTraceMemoryDumpImpl::setDiscardableMemoryBacking(
    const char* dumpName,
    const SkDiscardableMemory& discardableMemoryObject)
{
    std::string name = dump_name_prefix_ + dumpName;
    DCHECK(!process_memory_dump_->GetAllocatorDump(name));
    const SkDiscardableMemoryChrome& discardable_memory_obj = static_cast<const SkDiscardableMemoryChrome&>(discardableMemoryObject);
    auto dump = discardable_memory_obj.CreateMemoryAllocatorDump(
        name.c_str(), process_memory_dump_);
    DCHECK(dump);
}

SkTraceMemoryDump::LevelOfDetail SkiaTraceMemoryDumpImpl::getRequestedDetails()
    const
{
    return request_level_;
}

} // namespace skia
